package com.beta.cust.bind.datasync.service.impl;

import com.alibaba.fastjson.JSON;
import com.beta.cat.service.RedissonService;
import com.beta.cat.utils.GJsonUtil;
import com.beta.cat.utils.http.HttpManager;
import com.beta.cust.bind.datasync.config.CfgSelfRefreshBean;
import com.beta.cust.bind.datasync.constant.RedisConstant;
import com.beta.cust.bind.datasync.constant.WxWorkUrlContants;
import com.beta.cust.bind.datasync.constant.WeixinContants;
import com.beta.cust.bind.datasync.dto.WeixinGetAccessTokenRespDto;
import com.beta.cust.bind.datasync.service.IAccessTokenService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author：chenlei
 * @Date：2024/3/13 19:33
 */

@Slf4j
@Service
public class IAccessTokenServiceImpl implements IAccessTokenService {
    @Resource
    private RedissonService redissonService;

    @Autowired
    private HttpManager httpManager;
    @Resource
    private WeixinContants weixinContants;

    @Autowired
    private CfgSelfRefreshBean cfgSelfRefreshBean;

    /**
     * 根据 企业ID&企业secretKey 获取token
     * 详情见：https://work.weixin.qq.com/api/doc/90000/90135/91039
     *
     * @param corpId
     * @param secretKey
     * @return
     */
    @Override
    public String getAccessToken(String corpId, String secretKey) {
        String accessToken = StringUtils.EMPTY;

        //1.先去缓存里面查询有没有access_token
        String accessTokenKey = String.format(RedisConstant.ACCESS_TOKEN_KEY, corpId, secretKey);
        String accessTokenRedisResult = redissonService.getStr(accessTokenKey);
        if (StringUtils.isNotBlank(accessTokenRedisResult)) {
            accessToken = accessTokenRedisResult;
            return accessToken;
        }

        //2.加锁，保证只能有一个线程去获取企业微信的access_token
        String lockName = corpId + secretKey;
        try {
            if (redissonService.tryLock(lockName, RedisConstant.ACCESS_TOKEN_LOCK_TIME, RedisConstant.ACCESS_TOKEN_LOCK_TIME)) {

                //3.再去缓存里判断一次有没有access_token
                accessTokenRedisResult = redissonService.getStr(accessTokenKey);
                if (StringUtils.isNotBlank(accessTokenRedisResult)) {
                    accessToken = accessTokenRedisResult;
                    return accessToken;
                }

                //4.调用企微接口 获取accessToken
                WeixinGetAccessTokenRespDto weixinGetAccessTokenRespDto = httpManager.get(weixinContants.getAccessTokenUrl()
                        + "?corpid=" + corpId
                        + "&corpsecret=" + secretKey, WeixinGetAccessTokenRespDto.class);

                if (weixinGetAccessTokenRespDto.getErrcode() == WeixinContants.SUCCESS_CODE) {
                    // 放入redis
                    redissonService.set(accessTokenKey, weixinGetAccessTokenRespDto.getAccess_token(), (weixinGetAccessTokenRespDto.getExpires_in() - 180) * 1000L);
                    accessToken = weixinGetAccessTokenRespDto.getAccess_token();
                } else {
                    log.info("corpid{},corpsecret{}调用企业微信获取access_token出,报错信息是:{}", corpId, secretKey, JSON.toJSONString(weixinGetAccessTokenRespDto));
                }
            }
        } catch (Exception e) {
            log.error("corpid{},corpsecret{}调用企业微信获取access_token出错,信息是：{}", corpId, secretKey, e);
        } finally {
            redissonService.unlock(lockName);
        }
        return accessToken;
    }

    @Override
    public String getCorpToken(String corpId, String agentid) {
        String accessToken = StringUtils.EMPTY;

        //1.先去缓存里面查询有没有access_token
        String accessTokenKey = String.format(RedisConstant.CORP_ACCESS_TOKEN_KEY, corpId, agentid);
        String accessTokenRedisResult = redissonService.getStr(accessTokenKey);
        if (StringUtils.isNotBlank(accessTokenRedisResult)) {
            accessToken = accessTokenRedisResult;
            return accessToken;
        }

        //2.加锁，保证只能有一个线程去获取企业微信的access_token
        String lockName = corpId + agentid;
        try {
            if (redissonService.tryLock(lockName, RedisConstant.ACCESS_TOKEN_LOCK_TIME, RedisConstant.ACCESS_TOKEN_LOCK_TIME)) {

                //3.再去缓存里判断一次有没有access_token
                accessTokenRedisResult = redissonService.getStr(accessTokenKey);
                if (StringUtils.isNotBlank(accessTokenRedisResult)) {
                    accessToken = accessTokenRedisResult;
                    return accessToken;
                }

                //4.调用企微接口 获取accessToken
                String url = WxWorkUrlContants.CORP_ACCESS_TOKEN_URL + getAccessToken(cfgSelfRefreshBean.getCorpId(), cfgSelfRefreshBean.getCorpSecret());
                Map<String, Object> param = new HashMap<>();
                param.put("corpid", corpId);
                param.put("business_type", 1);
                param.put("agentid", agentid);
                WeixinGetAccessTokenRespDto weixinGetAccessTokenRespDto = httpManager.post(url, WeixinGetAccessTokenRespDto.class, GJsonUtil.toJson(param));
                if (weixinGetAccessTokenRespDto.getErrcode() == WeixinContants.SUCCESS_CODE) {
                    // 放入redis
                    redissonService.set(accessTokenKey, weixinGetAccessTokenRespDto.getAccess_token(), (weixinGetAccessTokenRespDto.getExpires_in() - 180) * 1000L);
                    accessToken = weixinGetAccessTokenRespDto.getAccess_token();
                } else {
                    log.info("corpid{},corpsecret{}调用企业微信获取access_token出,报错信息是:{}", corpId, agentid, JSON.toJSONString(weixinGetAccessTokenRespDto));
                }
            }
        } catch (Exception e) {
            log.error("corpid{},corpsecret{}调用企业微信获取access_token出错,信息是：{}", corpId, agentid, e);
        } finally {
            redissonService.unlock(lockName);
        }
        return accessToken;
    }
}
